<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>幂等性与重复操作解决方案 | 技术小馆</title>
    <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/6.4.0/css/all.min.css">
    <link rel="stylesheet" href="https://cdn.staticfile.org/tailwindcss/2.2.19/tailwind.min.css">
    <link href="https://fonts.googleapis.com/css2?family=Noto+Serif+SC:wght@400;500;600;700&family=Noto+Sans+SC:wght@300;400;500;700&display=swap" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/mermaid@latest/dist/mermaid.min.js"></script>
    <style>
        body {
            font-family: 'Noto Sans SC', Tahoma, Arial, Roboto, "Droid Sans", "Helvetica Neue", "Droid Sans Fallback", "Heiti SC", "Hiragino Sans GB", Simsun, sans-serif;
            background-color: #f8fafc;
            color: #1e293b;
        }
        h1, h2, h3, h4 {
            font-family: 'Noto Serif SC', serif;
            font-weight: 600;
        }
        .hero-section {
            background: linear-gradient(135deg, #4f46e5 0%, #7c3aed 100%);
        }
        .code-block {
            background-color: #1e293b;
            border-left: 4px solid #7c3aed;
        }
        .card-hover {
            transition: all 0.3s ease;
        }
        .card-hover:hover {
            transform: translateY(-5px);
            box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
        }
        .section-divider {
            height: 1px;
            background: linear-gradient(90deg, transparent, rgba(79, 70, 229, 0.5), transparent);
        }
    </style>
</head>
<body>
    <!-- Hero Section -->
    <section class="hero-section text-white py-20 px-6">
        <div class="container mx-auto max-w-5xl">
            <div class="flex flex-col items-center text-center">
                <div class="mb-6">
                    <span class="inline-block px-4 py-2 bg-white bg-opacity-20 rounded-full text-sm font-semibold tracking-wider">
                        <i class="fas fa-shield-alt mr-2"></i>系统设计
                    </span>
                </div>
                <h1 class="text-4xl md:text-5xl font-bold mb-6 leading-tight">幂等性与重复操作解决方案</h1>
                <p class="text-xl md:text-2xl max-w-3xl opacity-90 leading-relaxed">
                    通过精心设计的策略，确保系统在面临重复请求时依然保持稳定性和数据一致性
                </p>
                <div class="mt-10 flex space-x-4">
                    <a href="#solutions" class="px-8 py-3 bg-white text-indigo-600 font-semibold rounded-lg hover:bg-opacity-90 transition">
                        <i class="fas fa-lightbulb mr-2"></i>解决方案
                    </a>
                    <a href="#visualization" class="px-8 py-3 border-2 border-white text-white font-semibold rounded-lg hover:bg-white hover:bg-opacity-10 transition">
                        <i class="fas fa-project-diagram mr-2"></i>可视化指南
                    </a>
                </div>
            </div>
        </div>
    </section>

    <!-- Intro Section -->
    <section class="py-16 px-6 bg-white">
        <div class="container mx-auto max-w-5xl">
            <div class="text-center mb-12">
                <h2 class="text-3xl font-bold mb-4">为什么需要解决幂等性问题？</h2>
                <div class="max-w-3xl mx-auto text-gray-600">
                    <p class="mb-4">在现代分布式系统中，网络延迟、用户重复操作或系统重试机制都可能导致重复请求。如果没有正确处理这些情况，可能会导致数据不一致、重复扣款或其他业务异常。</p>
                    <p>通过实现幂等性设计，我们可以确保无论同一操作执行多少次，结果都是相同的，从而提升系统的鲁棒性和用户体验。</p>
                </div>
            </div>
        </div>
    </section>

    <!-- Main Content -->
    <section id="solutions" class="py-16 px-6 bg-gray-50">
        <div class="container mx-auto max-w-5xl">
            <!-- 1. 幂等性设计 -->
            <div class="mb-20">
                <div class="flex items-center mb-6">
                    <div class="w-12 h-12 rounded-full bg-indigo-100 flex items-center justify-center mr-4">
                        <span class="text-indigo-600 text-xl font-bold">1</span>
                    </div>
                    <h2 class="text-2xl font-bold">幂等性设计</h2>
                </div>
                <p class="text-gray-600 mb-8">幂等性是指无论同一操作执行多少次，结果都是相同的。为了实现幂等性，可以采取以下措施：</p>
                
                <!-- 1.1 使用唯一标识符 -->
                <div class="mb-12">
                    <div class="flex items-center mb-4">
                        <div class="w-8 h-8 rounded-full bg-indigo-50 flex items-center justify-center mr-3">
                            <span class="text-indigo-600 text-sm font-bold">1.1</span>
                        </div>
                        <h3 class="text-xl font-semibold">使用唯一标识符（ID）</h3>
                    </div>
                    <div class="bg-white rounded-xl shadow-md overflow-hidden card-hover">
                        <div class="p-6">
                            <p class="text-gray-600 mb-4">每个请求附带一个唯一标识符，如订单号、请求 ID 或事务 ID。服务器端在处理请求时，首先检查这个 ID 是否已经处理过，如果处理过，则返回之前的结果，避免重复处理。</p>
                            <div class="code-block rounded-lg p-4 text-gray-200 overflow-x-auto">
                                <pre><code>public class IdempotentService {

    private Set&lt;String&gt; processedIds = new HashSet&lt;&gt;();

    public synchronized String processRequest(String requestId) {
        if (processedIds.contains(requestId)) {
            return "Request already processed.";
        }
        processedIds.add(requestId);
        // 处理业务逻辑
        return "Request processed successfully.";
    }
}</code></pre>
                            </div>
                            <div class="mt-4 flex items-center text-sm text-gray-500">
                                <i class="fas fa-info-circle mr-2"></i>
                                <span>适用于：订单创建、支付请求等需要确保不重复处理的场景</span>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- 1.2 使用数据库事务 -->
                <div class="mb-12">
                    <div class="flex items-center mb-4">
                        <div class="w-8 h-8 rounded-full bg-indigo-50 flex items-center justify-center mr-3">
                            <span class="text-indigo-600 text-sm font-bold">1.2</span>
                        </div>
                        <h3 class="text-xl font-semibold">使用数据库事务</h3>
                    </div>
                    <div class="bg-white rounded-xl shadow-md overflow-hidden card-hover">
                        <div class="p-6">
                            <p class="text-gray-600 mb-4">数据库操作通常支持事务机制。通过将操作封装在事务中，可以确保操作的原子性，避免因重复请求导致的数据不一致。</p>
                            <div class="code-block rounded-lg p-4 text-gray-200 overflow-x-auto">
                                <pre><code>@Transactional
public void performDatabaseOperation() {
    // 数据库操作
}</code></pre>
                            </div>
                            <div class="mt-4 flex items-center text-sm text-gray-500">
                                <i class="fas fa-info-circle mr-2"></i>
                                <span>适用于：需要保证数据一致性的数据库操作</span>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- 1.3 使用分布式锁 -->
                <div class="mb-12">
                    <div class="flex items-center mb-4">
                        <div class="w-8 h-8 rounded-full bg-indigo-50 flex items-center justify-center mr-3">
                            <span class="text-indigo-600 text-sm font-bold">1.3</span>
                        </div>
                        <h3 class="text-xl font-semibold">使用分布式锁</h3>
                    </div>
                    <div class="bg-white rounded-xl shadow-md overflow-hidden card-hover">
                        <div class="p-6">
                            <p class="text-gray-600 mb-4">在分布式环境中，可以使用分布式锁（如 Redis 的分布式锁）来防止同一操作被多次执行。分布式锁确保在同一时间只有一个请求能够执行某个操作。</p>
                            <div class="code-block rounded-lg p-4 text-gray-200 overflow-x-auto">
                                <pre><code>public class DistributedLockService {

    private final RedisTemplate&lt;String, String&gt; redisTemplate;

    public void performOperationWithLock(String lockKey) {
        Boolean acquired = redisTemplate.opsForValue()
            .setIfAbsent(lockKey, "locked", 5, TimeUnit.MINUTES);
        if (Boolean.TRUE.equals(acquired)) {
            try {
                // 执行操作
            } finally {
                redisTemplate.delete(lockKey);
            }
        } else {
            // 锁未获取，操作正在进行中
        }
    }
}</code></pre>
                            </div>
                            <div class="mt-4 flex items-center text-sm text-gray-500">
                                <i class="fas fa-info-circle mr-2"></i>
                                <span>适用于：分布式环境下的资源竞争场景</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="section-divider my-12"></div>

            <!-- 2. 防止重复提交 -->
            <div class="mb-20">
                <div class="flex items-center mb-6">
                    <div class="w-12 h-12 rounded-full bg-indigo-100 flex items-center justify-center mr-4">
                        <span class="text-indigo-600 text-xl font-bold">2</span>
                    </div>
                    <h2 class="text-2xl font-bold">防止重复提交</h2>
                </div>

                <!-- 2.1 客户端防重 -->
                <div class="mb-12">
                    <div class="flex items-center mb-4">
                        <div class="w-8 h-8 rounded-full bg-indigo-50 flex items-center justify-center mr-3">
                            <span class="text-indigo-600 text-sm font-bold">2.1</span>
                        </div>
                        <h3 class="text-xl font-semibold">客户端防重</h3>
                    </div>
                    <div class="bg-white rounded-xl shadow-md overflow-hidden card-hover">
                        <div class="p-6">
                            <p class="text-gray-600 mb-4">在客户端（如浏览器）中，可以禁用按钮点击多次，或者在点击后禁用按钮，防止用户重复提交请求。</p>
                            <div class="flex items-center p-4 bg-gray-50 rounded-lg">
                                <div class="mr-4">
                                    <button class="px-6 py-2 bg-indigo-600 text-white rounded-md hover:bg-indigo-700 transition">提交订单</button>
                                </div>
                                <div>
                                    <button class="px-6 py-2 bg-indigo-600 text-white rounded-md opacity-75 cursor-not-allowed" disabled>
                                        <i class="fas fa-spinner fa-spin mr-2"></i>处理中...
                                    </button>
                                </div>
                            </div>
                            <div class="mt-4 flex items-center text-sm text-gray-500">
                                <i class="fas fa-info-circle mr-2"></i>
                                <span>简单有效的前端解决方案，提升用户体验</span>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- 2.2 后端去重 -->
                <div class="mb-12">
                    <div class="flex items-center mb-4">
                        <div class="w-8 h-8 rounded-full bg-indigo-50 flex items-center justify-center mr-3">
                            <span class="text-indigo-600 text-sm font-bold">2.2</span>
                        </div>
                        <h3 class="text-xl font-semibold">后端去重</h3>
                    </div>
                    <div class="bg-white rounded-xl shadow-md overflow-hidden card-hover">
                        <div class="p-6">
                            <p class="text-gray-600 mb-4">后端系统可以通过数据库或缓存系统来记录请求，防止相同请求被重复处理。例如，可以在处理请求时，将请求信息存储在缓存中，并设置超时时间来清理过期的请求记录。</p>
                            <div class="code-block rounded-lg p-4 text-gray-200 overflow-x-auto">
                                <pre><code>public class RequestDeduplicationService {

    private final Cache&lt;String, Boolean&gt; cache = CacheBuilder.newBuilder()
        .expireAfterWrite(10, TimeUnit.MINUTES)
        .build();

    public boolean processRequest(String requestId) {
        if (cache.getIfPresent(requestId) != null) {
            return false; // 请求已处理
        }
        cache.put(requestId, true);
        // 处理请求
        return true; // 请求处理成功
    }
}</code></pre>
                            </div>
                            <div class="mt-4 flex items-center text-sm text-gray-500">
                                <i class="fas fa-info-circle mr-2"></i>
                                <span>适用于：需要后端确保请求唯一性的场景</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>

            <div class="section-divider my-12"></div>

            <!-- 3. 业务逻辑中的幂等性 -->
            <div class="mb-20">
                <div class="flex items-center mb-6">
                    <div class="w-12 h-12 rounded-full bg-indigo-100 flex items-center justify-center mr-4">
                        <span class="text-indigo-600 text-xl font-bold">3</span>
                    </div>
                    <h2 class="text-2xl font-bold">业务逻辑中的幂等性</h2>
                </div>

                <!-- 3.1 订单系统 -->
                <div class="mb-12">
                    <div class="flex items-center mb-4">
                        <div class="w-8 h-8 rounded-full bg-indigo-50 flex items-center justify-center mr-3">
                            <span class="text-indigo-600 text-sm font-bold">3.1</span>
                        </div>
                        <h3 class="text-xl font-semibold">订单系统</h3>
                    </div>
                    <div class="bg-white rounded-xl shadow-md overflow-hidden card-hover">
                        <div class="p-6">
                            <p class="text-gray-600 mb-4">在订单系统中，可以通过检查订单状态来保证幂等性。重复的订单请求将不会创建新的订单，而是返回已经存在的订单信息。</p>
                            <div class="code-block rounded-lg p-4 text-gray-200 overflow-x-auto">
                                <pre><code>public class OrderService {

    public Order processOrder(String orderId) {
        Order order = orderRepository.findById(orderId);
        if (order != null) {
            return order; // 订单已存在，返回已存在的订单
        }
        // 创建新订单
        return createNewOrder(orderId);
    }
}</code></pre>
                            </div>
                            <div class="mt-4 flex items-center text-sm text-gray-500">
                                <i class="fas fa-info-circle mr-2"></i>
                                <span>适用于：电商、外卖等订单处理系统</span>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- 3.2 支付系统 -->
                <div class="mb-12">
                    <div class="flex items-center mb-4">
                        <div class="w-8 h-8 rounded-full bg-indigo-50 flex items-center justify-center mr-3">
                            <span class="text-indigo-600 text-sm font-bold">3.2</span>
                        </div>
                        <h3 class="text-xl font-semibold">支付系统</h3>
                    </div>
                    <div class="bg-white rounded-xl shadow-md overflow-hidden card-hover">
                        <div class="p-6">
                            <p class="text-gray-600 mb-4">在支付系统中，使用支付交易 ID 来确保每个交易只处理一次。如果交易 ID 已经存在于数据库中，则表示交易已经处理过，避免重复处理。</p>
                            <div class="code-block rounded-lg p-4 text-gray-200 overflow-x-auto">
                                <pre><code>public class PaymentService {

    public void processPayment(String transactionId) {
        if (paymentRepository.existsById(transactionId)) {
            return; // 交易已处理
        }
        // 处理支付
    }
}</code></pre>
                            </div>
                            <div class="mt-4 flex items-center text-sm text-gray-500">
                                <i class="fas fa-info-circle mr-2"></i>
                                <span>适用于：支付网关、财务系统等关键业务场景</span>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Visualization Section -->
    <section id="visualization" class="py-16 px-6 bg-white">
        <div class="container mx-auto max-w-5xl">
            <div class="text-center mb-12">
                <h2 class="text-3xl font-bold mb-4">幂等性解决方案关系图</h2>
                <p class="max-w-3xl mx-auto text-gray-600">不同场景下的幂等性解决方案及其相互关系</p>
            </div>
            
            <div class="bg-gray-50 p-6 rounded-xl mb-12">
                <div class="mermaid">
                    graph TD
                    A[幂等性解决方案] --> B[幂等性设计]
                    A --> C[防止重复提交]
                    A --> D[业务逻辑幂等性]
                    
                    B --> B1[使用唯一标识符]
                    B --> B2[数据库事务]
                    B --> B3[分布式锁]
                    
                    C --> C1[客户端防重]
                    C --> C2[后端去重]
                    
                    D --> D1[订单系统]
                    D --> D2[支付系统]
                    
                    style A fill:#4f46e5,stroke:#4f46e5,color:white
                    style B fill:#7c3aed,stroke:#7c3aed,color:white
                    style C fill:#7c3aed,stroke:#7c3aed,color:white
                    style D fill:#7c3aed,stroke:#7c3aed,color:white
                </div>
            </div>

            <div class="bg-indigo-50 p-8 rounded-xl">
                <div class="flex flex-col md:flex-row items-center">
                    <div class="md:w-1/2 mb-6 md:mb-0">
                        <h3 class="text-2xl font-bold mb-4">需要专业的架构咨询？</h3>
                        <p class="text-gray-600 mb-4">我们的技术专家团队可以帮助您设计高可用的分布式系统架构，解决幂等性和数据一致性问题。</p>
                        <button class="px-6 py-3 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 transition flex items-center">
                            <i class="fas fa-envelope mr-2"></i> 联系我们
                        </button>
                    </div>
                    <div class="md:w-1/2 flex justify-center">
                        <div class="w-48 h-48 bg-white rounded-full shadow-lg flex items-center justify-center">
                            <i class="fas fa-headset text-6xl text-indigo-600"></i>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>

    <!-- Footer -->
    <footer class="bg-gray-900 text-gray-300 py-12 px-6">
        <div class="container mx-auto max-w-5xl">
            <div class="flex flex-col items-center text-center">
                <div class="mb-4">
                    <span class="text-xl font-bold text-white">技术小馆</span>
                </div>
                <div class="mb-6">
                    <a href="http://www.yuque.com/jtostring" class="text-indigo-400 hover:text-white transition">http://www.yuque.com/jtostring</a>
                </div>
                <div class="text-sm text-gray-500">
                    © 2023 技术小馆. All rights reserved.
                </div>
            </div>
        </div>
    </footer>

    <script>
        mermaid.initialize({
            startOnLoad: true,
            theme: 'default',
            flowchart: {
                useMaxWidth: true,
                htmlLabels: true,
                curve: 'basis'
            }
        });
    </script>
</body>
</html>